using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;

namespace ICSharpCode.TextEditor.Document
{
	public class HighlightingManager
	{
		private ArrayList syntaxModeFileProviders = new ArrayList();

		private static HighlightingManager highlightingManager;

		private Hashtable highlightingDefs = new Hashtable();

		private Hashtable extensionsToName = new Hashtable();

		public Hashtable HighlightingDefinitions => this.highlightingDefs;

		public static HighlightingManager Manager => HighlightingManager.highlightingManager;

		public DefaultHighlightingStrategy DefaultHighlighting => (DefaultHighlightingStrategy)this.highlightingDefs["Default"];

		public event EventHandler ReloadSyntaxHighlighting;

		static HighlightingManager()
		{
			HighlightingManager.highlightingManager = new HighlightingManager();
			HighlightingManager.highlightingManager.AddSyntaxModeFileProvider(new ResourceSyntaxModeProvider());
		}

		public HighlightingManager()
		{
			this.CreateDefaultHighlightingStrategy();
		}

		public void AddSyntaxModeFileProvider(ISyntaxModeFileProvider syntaxModeFileProvider)
		{
			foreach (SyntaxMode syntaxMode in syntaxModeFileProvider.SyntaxModes)
			{
				this.highlightingDefs[syntaxMode.Name] = new DictionaryEntry(syntaxMode, syntaxModeFileProvider);
				string[] extensions = syntaxMode.Extensions;
				foreach (string text in extensions)
				{
					this.extensionsToName[text.ToUpperInvariant()] = syntaxMode.Name;
				}
			}
			if (!this.syntaxModeFileProviders.Contains(syntaxModeFileProvider))
			{
				this.syntaxModeFileProviders.Add(syntaxModeFileProvider);
			}
		}

		public void AddHighlightingStrategy(IHighlightingStrategy highlightingStrategy)
		{
			this.highlightingDefs[highlightingStrategy.Name] = highlightingStrategy;
			string[] extensions = highlightingStrategy.Extensions;
			foreach (string text in extensions)
			{
				this.extensionsToName[text.ToUpperInvariant()] = highlightingStrategy.Name;
			}
		}

		public void ReloadSyntaxModes()
		{
			this.highlightingDefs.Clear();
			this.extensionsToName.Clear();
			this.CreateDefaultHighlightingStrategy();
			foreach (ISyntaxModeFileProvider syntaxModeFileProvider in this.syntaxModeFileProviders)
			{
				syntaxModeFileProvider.UpdateSyntaxModeList();
				this.AddSyntaxModeFileProvider(syntaxModeFileProvider);
			}
			this.OnReloadSyntaxHighlighting(EventArgs.Empty);
		}

		private void CreateDefaultHighlightingStrategy()
		{
			DefaultHighlightingStrategy defaultHighlightingStrategy = new DefaultHighlightingStrategy();
			defaultHighlightingStrategy.Extensions = new string[0];
			defaultHighlightingStrategy.Rules.Add(new HighlightRuleSet());
			this.highlightingDefs["Default"] = defaultHighlightingStrategy;
		}

		private IHighlightingStrategy LoadDefinition(DictionaryEntry entry)
		{
			SyntaxMode syntaxMode = (SyntaxMode)entry.Key;
			ISyntaxModeFileProvider syntaxModeFileProvider = (ISyntaxModeFileProvider)entry.Value;
			DefaultHighlightingStrategy defaultHighlightingStrategy = null;
			try
			{
				XmlTextReader syntaxModeFile = syntaxModeFileProvider.GetSyntaxModeFile(syntaxMode);
				if (syntaxModeFile == null)
				{
					throw new HighlightingDefinitionInvalidException("Could not get syntax mode file for " + syntaxMode.Name);
				}
				defaultHighlightingStrategy = HighlightingDefinitionParser.Parse(syntaxMode, syntaxModeFile);
				if (defaultHighlightingStrategy.Name != syntaxMode.Name)
				{
					throw new HighlightingDefinitionInvalidException("The name specified in the .xshd '" + defaultHighlightingStrategy.Name + "' must be equal the syntax mode name '" + syntaxMode.Name + "'");
				}
			}
			finally
			{
				if (defaultHighlightingStrategy == null)
				{
					defaultHighlightingStrategy = this.DefaultHighlighting;
				}
				this.highlightingDefs[syntaxMode.Name] = defaultHighlightingStrategy;
				defaultHighlightingStrategy.ResolveReferences();
			}
			return defaultHighlightingStrategy;
		}

		internal KeyValuePair<SyntaxMode, ISyntaxModeFileProvider> FindHighlighterEntry(string name)
		{
			foreach (ISyntaxModeFileProvider syntaxModeFileProvider in this.syntaxModeFileProviders)
			{
				foreach (SyntaxMode syntaxMode in syntaxModeFileProvider.SyntaxModes)
				{
					if (syntaxMode.Name == name)
					{
						return new KeyValuePair<SyntaxMode, ISyntaxModeFileProvider>(syntaxMode, syntaxModeFileProvider);
					}
				}
			}
			return new KeyValuePair<SyntaxMode, ISyntaxModeFileProvider>(null, null);
		}

		public IHighlightingStrategy FindHighlighter(string name)
		{
			object obj = this.highlightingDefs[name];
			if (obj is DictionaryEntry)
			{
				return this.LoadDefinition((DictionaryEntry)obj);
			}
			object result;
			if (obj != null)
			{
				result = (IHighlightingStrategy)obj;
			}
			else
			{
				IHighlightingStrategy defaultHighlighting = this.DefaultHighlighting;
				result = defaultHighlighting;
			}
			return (IHighlightingStrategy)result;
		}

		public IHighlightingStrategy FindHighlighterForFile(string fileName)
		{
			string text = (string)this.extensionsToName[Path.GetExtension(fileName)!.ToUpperInvariant()];
			if (text != null)
			{
				object obj = this.highlightingDefs[text];
				if (obj is DictionaryEntry)
				{
					return this.LoadDefinition((DictionaryEntry)obj);
				}
				object result;
				if (obj != null)
				{
					result = (IHighlightingStrategy)obj;
				}
				else
				{
					IHighlightingStrategy defaultHighlighting = this.DefaultHighlighting;
					result = defaultHighlighting;
				}
				return (IHighlightingStrategy)result;
			}
			return this.DefaultHighlighting;
		}

		protected virtual void OnReloadSyntaxHighlighting(EventArgs e)
		{
			if (this.ReloadSyntaxHighlighting != null)
			{
				this.ReloadSyntaxHighlighting(this, e);
			}
		}
	}
}
